package com.pince.pushStreaming.pusher

import android.content.Context
import android.hardware.Camera
import android.util.AttributeSet
import android.util.Log
import android.view.Gravity
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.TextView
import com.example.plstreaming.R
import com.qiniu.pili.droid.streaming.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.nio.ByteBuffer

abstract class PLStreamListener : FrameLayout, StreamingStateChangedListener, StreamStatusCallback, AudioSourceCallback, StreamingSessionListener {

    constructor(context: Context) : super(context)
    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)

    var params: LayoutParams = LayoutParams(
            ViewGroup.LayoutParams.WRAP_CONTENT,
            ViewGroup.LayoutParams.WRAP_CONTENT,
            Gravity.CENTER)


    companion object {
        var isDebug = true
        val TAG = "PLStream_"
    }

    lateinit var logTextView: TextView

    init {
        if (isDebug) {
            logTextView = TextView(context)
            logTextView.layoutParams = params
        }
    }

    /**
     *  {@link StreamingState}更改时调用。
     *
     *  @param指定的{@link StreamingState}状态。
     *  @param额外的额外信息。
     **/
    private var mStatusMsgContent: String = "null"
    override fun onStateChanged(streamingState: StreamingState?, p1: Any?) {
        when (streamingState) {
            //网络环境
            StreamingState.PREPARING -> {
                mStatusMsgContent += context.getString(R.string.string_state_preparing)+'\n'
            }
            StreamingState.READY -> {
                mStatusMsgContent += context.getString(R.string.string_state_ready)+'\n'
            }
            StreamingState.CONNECTING -> {
                mStatusMsgContent += context.getString(R.string.string_state_connecting)+'\n'
            }
            StreamingState.STREAMING -> {
                mStatusMsgContent += context.getString(R.string.string_state_streaming)+'\n'
            }
            StreamingState.SHUTDOWN -> {
                mStatusMsgContent += context.getString(R.string.string_state_ready)+'\n'
            }
            StreamingState.IOERROR -> {
                mStatusMsgContent += context.getString(R.string.string_state_error)+'\n'
            }
            StreamingState.DISCONNECTED -> {
                mStatusMsgContent += context.getString(R.string.string_state_con_disconnected)+'\n'
            }
            StreamingState.UNKNOWN -> {
                mStatusMsgContent += context.getString(R.string.string_state_unknown)+'\n'
            }
            StreamingState.SENDING_BUFFER_EMPTY -> {
            }
            StreamingState.SENDING_BUFFER_FULL -> {
            }
            StreamingState.AUDIO_RECORDING_FAIL -> {
            }
            StreamingState.INVALID_STREAMING_URL -> {
            }
            StreamingState.UNAUTHORIZED_STREAMING_URL -> {
                mStatusMsgContent += context.getString(R.string.string_state_unauthorized_streaming_url)+'\n'
            }
            else -> {

            }
        }
        setLogs(mStatusMsgContent)
    }

    fun setLogs(string: String) {
        if (isDebug) {
            Log.e(TAG, string)
            GlobalScope.launch(Dispatchers.Main) {
                logTextView.text = string
            }
        }
    }

    /**
     * 根据{@StreamingProfile.StreamStatusConfig#getIntervalMs}链接调用。
     *
     * @param status新的{@link StreamingProfile.StreamStatus}。
     *。     注意：notifyStreamStatusChanged 运行在非 UI 线程中。
     **/
    override fun notifyStreamStatusChanged(p0: StreamingProfile.StreamStatus?) {
    }

    /**
     * 回调音频采集 PCM 数据
     *
     * @param srcBuffer     音频 PCM数据，该 buffer 是 direct ByteBuffer。
     * @param size          buffer的大小
     * @param tsInNanoTime  时间戳，单位：纳秒
     * @param isEof         采集结束标志
     */
    override fun onAudioSourceAvailable(p0: ByteBuffer?, p1: Int, p2: Long, p3: Boolean) {
    }

    /**
     *  重新启动流通知。
     *  <p>
     *  当网络连接断开时，会先通知{@link StreamingState#Disconnect}。
     *  如果重启流媒体的环境准备好了，则调用该方法。
     *
     *  <p>
     *  SDK不会限制调用次数。
     *
     *  @param code错误码。<b>现在未指定</b>。
     *  @return true表示您处理了事件；否则，放弃，然后{@link StreamingState#Shutdown}。
     *  将会收到通知。
     **/
    override fun onRestartStreamingHandled(p0: Int): Boolean {
        return startStreaming()
    }


    /**
     * 在构建摄像头对象后调用。
     * <p>。
     * 支持列表存在于以下情况：
     * <ol>。
     * <li>如果没有设置。
     * {@link CameraStreamingSetting#setCameraPrvSizeRatio}何时。
     * 初始化{@link CameraStreamingSetting}，
     * 将传递整个支持列表</li>。
     * <li>if{@link CameraStreamingSetting#setCameraPrvSizeRatio}。
     * 已设置，则传递按指定比例过滤后支持的预览大小</li>。
     * </ol>。
     *
     * @param list支持摄像头预览列表，从小到大排序。该列表可能为空。
     *
     * @return null表示您放弃选择，SDK会帮您选择合适的预览。
     * Size，否则返回的大小有效。
     *
     **/
    override fun onPreviewSizeSelected(list: MutableList<Camera.Size>?): Camera.Size? {
        return null
    }

    /**
     *  自定义预览fps，在构建Camera对象后调用。
     *
     * @param supportedPreviewFpsRange。
     * 按摄像机显示支持的预览fps范围列表。此方法返回一个。
     * 至少包含一个元素的列表。每个元素都是一个整型数组。
     * 有两个值-最小fps和最大fps。
     * @return-1表示放弃选择，SDK会帮您选择合适的预览。
     * fps，否则返回的索引有效。
     */
    override fun onPreviewFpsSelected(p0: MutableList<IntArray>?): Int {
        return -1
    }

    /**
     *  录音失败时调用。
     *  <p>
     *
     *  @param code错误码。<b>现在未指定</b>。
     *
     *  @return true表示事件已处理，否则放弃。
     *
     **/
    override fun onRecordAudioFailedHandled(p0: Int): Boolean {
        setStreamEncodingType()
        return true
    }

    abstract fun setStreamEncodingType()
    abstract fun startStreaming(): Boolean

}